﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace RoslynDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 指定源代码。这里用的是直接中文本框中获取，当然也可以用其他的方式代替
            SourceText st = SourceText.From(txbCode.Text); 
            // 指定源代码2。也可以直接用文本的方式
            st = SourceText.From(@"public class TestRoslyn { public void Test(){ Console.FakeMethod(); } }");
            // 确定使用C# 的版本和传入的预编译量
            CSharpParseOptions option = new CSharpParseOptions(LanguageVersion.CSharp6, preprocessorSymbols: new List<string>() { "Debug" });
            // 生成语法树。有做过反编译的工程师大多都知道语法树，这个是反编译的关键。
            var tree = CSharpSyntaxTree.ParseText(st, option);
            // debug
            Debug.Assert(tree.GetDiagnostics().ToList().Count == 0);

            // 声明编译选项
            var compileOption = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
            // 创建编译实例
            var compilation = CSharpCompilation.Create(
            "class1",
            new List<SyntaxTree> { tree }, //这是前面生成的语法树
            new List<MetadataReference>() { MetadataReference.CreateFromFile(typeof(int).Assembly.Location) }, 
            compileOption);
            Debug.Assert(tree.GetDiagnostics().ToList().Count == 0); //如果之前有引用缺失、调用方法错误，这里就会体现出来

            var assemblyPath = @"class1.dll";
            var pdbPath = @"class1.pdb";
            // 编译输出文件
            var res = compilation.Emit(assemblyPath, pdbPath); //result表明了执行是否成功
        }
    }
}
